package dragon.core.util;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import dragon.core.exception.ExceptionHandler;

public class StringUtils {

	private static final Logger logger = LoggerFactory.getLogger(StringUtils.class);

	/**
	 * 判断字符串是否为空
	 * 
	 * @param str
	 *            如果字符串为null,"null"或者为空，都将返回true，否则返回false
	 * @return
	 */
	public static boolean isEmpty(String str) {
		if (str == null || "".equals(str.trim()) || "null".equalsIgnoreCase(str.trim())) {
			return true;
		}
		return false;
	}

	/**
	 * 清洗字符串
	 * 
	 * @param str
	 *            待清晰的字符串
	 * @param defaultValue
	 *            默认替换值
	 * @return
	 */
	public static String clear(String str, String defaultValue) {
		if (isEmpty(str)) {
			return defaultValue;
		} else {
			return str.trim();
		}
	}

	/**
	 * 判断端口号是否正确
	 * 
	 * @param port
	 * @return
	 */
	public static boolean isPort(String port) {
		if (isEmpty(port)) {
			return false;
		}
		try {
			Integer i = Integer.parseInt(port);
			if (i >= 0 && i <= 65535) {
				return true;
			}
			return false;// 不在端口范围
		} catch (Exception e) {
			// 非数字串
			return false;
		}
	}

	/**
	 * 判断字符串是否可转换为Long类型
	 * 
	 * @param longStr
	 * @return
	 */
	public static boolean isLong(String longStr) {
		if (isEmpty(longStr)) {
			return false;
		}
		try {
			Long.parseLong(longStr);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 判断字符串是否可转换为Integer类型
	 * 
	 * @param intStr
	 * @return
	 */
	public static boolean isInteger(String intStr) {
		if (isEmpty(intStr)) {
			return false;
		}
		try {
			Integer.parseInt(intStr);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 判断字符串是否可转换为BigDecimal类型
	 * 
	 * @param decimalStr
	 * @return
	 */
	public static boolean isDecimal(String decimalStr) {
		try {
			new BigDecimal(decimalStr);
			return true;
		} catch (NumberFormatException e) {
			return false;
		}
	}

	/**
	 * 将数值型字符串转换为数字
	 * 
	 * @param intStr
	 * @return
	 */
	public static int intValue(String intStr) {
		return Integer.parseInt(intStr);
	}

	/**
	 * 将长整形字符串转换为长整形数值
	 * 
	 * @param longStr
	 * @return
	 */
	public static long longValue(String longStr) {
		return Long.parseLong(longStr);
	}

	/**
	 * 将数值型字符串转换为数值型
	 * 
	 * @param decimalStr
	 * @return
	 */
	public static BigDecimal decimalValue(String decimalStr) {
		return new BigDecimal(decimalStr);
	}

	/**
	 * 将table名称转换成类名称
	 * 
	 * @param tableName
	 *            数据表名称
	 * @return
	 */
	public static String table2Class(String tableName) {

		String className = tableName;
		String _ = "_";

		// 去除两端空格
		className = className.trim();

		// 去除T_
		if (className.startsWith("t_")) {
			className = className.substring(2);
		}

		// 将首字母转换成大写
		className = className.substring(0, 1).toUpperCase() + className.substring(1);

		// 将下划线_后面的首字母转换为大写
		int index = className.indexOf(_);
		while (index > -1) {
			String left = className.substring(0, index);
			String right = className.substring(index + 1);

			if (right.length() > 0) {
				right = right.substring(0, 1).toUpperCase() + right.substring(1);
			}
			className = left + right;

			index = className.indexOf(_);
		}
		return className;
	}

	/**
	 * 将数据表的字段名称转换成对应的类属性名称
	 * 
	 * @param columnName
	 *            数据表字段名称
	 * @return
	 */
	public static String column2Field(String columnName) {

		String fieldName = columnName;
		String _ = "_";

		// 去除两端空格
		fieldName = fieldName.trim();

		// 将下划线_后面的首字母转换为大写
		int index = fieldName.indexOf(_);
		while (index > -1) {
			String left = fieldName.substring(0, index);
			String right = fieldName.substring(index + 1);

			if (right.length() > 0) {
				right = right.substring(0, 1).toUpperCase() + right.substring(1);
			}
			fieldName = left + right;

			index = fieldName.indexOf(_);
		}
		return fieldName;
	}

	/**
	 * 用于解决URL参数中文奇数乱码问题
	 * 
	 * @param s
	 * @return
	 */
	public static String encodeURL(String s) {
		String temp = "";
		if (!isEmpty(s)) {
			try {
				temp = java.net.URLEncoder.encode(s, "UTF-8");
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}
		return temp;
	}

	/**
	 * 判断给定的字符串是否可以用作包名
	 * 
	 * @return
	 */
	public static boolean isPackageNameCorrect(String pkgName) {
		boolean isCorrect = true;

		if (isEmpty(pkgName)) {
			return true;
		}

		pkgName = pkgName.trim().toLowerCase();// 去除两端空格，并转换为小写格式

		// 包命名规则：可以取以下字符，且只能以字母或下划线开始，用"."分隔包名，且最后一个字符不能为"."
		String criterionStr1 = "abcdefghijklmnopqrstuvwxyz_";
		String criterionStr2 = "0123456789.";

		char[] chars = pkgName.toCharArray();
		for (char c : chars) {
			if (!criterionStr1.contains(String.valueOf(c)) && !criterionStr2.contains(String.valueOf(c))) {
				return false;
			}
		}

		// 判断首字符
		char c = pkgName.charAt(0);
		if (!criterionStr1.contains(String.valueOf(c))) {
			return false;
		}

		// 判断尾字符
		if (pkgName.endsWith(".")) {
			return false;
		}

		return isCorrect;
	}

	/**
	 * 判断字符是否是中文
	 * 
	 * @param c
	 *            字符
	 * @return
	 */
	public static boolean isChinese(char c) {
		// 假定英文范围为0-127
		int enEnd = 127;
		int code = c;
		return code > enEnd;
	}

	/**
	 * 截取字符串
	 * 
	 * @param str
	 *            待截取的字符串
	 * @param len
	 *            截取长度(2个英文字符相当于一个中文字符)
	 * @return
	 */
	public static String cutString(String str, int len) {

		if (StringUtils.isEmpty(str)) {
			return "";
		}

		if (len <= 0 || len * 2 >= length(str)) {
			return str;// 字符长度未达到截断限制要求
		}

		int totalLength = 0;
		StringBuilder result = new StringBuilder();

		char[] chars = str.toCharArray();
		for (char c : chars) {
			if (totalLength < len * 2) {
				if (isChinese(c)) {
					if (totalLength + 2 <= len * 2) {
						result.append(c);
						totalLength += 2;
					} else {
						break;
					}
				} else {
					if (totalLength + 1 <= len * 2) {
						result.append(c);
						totalLength++;
					} else {
						break;
					}
				}
			} else {
				break;
			}
		}
		result.append("...");
		return result.toString();
	}

	/**
	 * 计算字符串长度(一个中文字符长度为2)
	 * 
	 * @param str
	 *            待计算的字符串
	 * @return
	 */
	public static int length(String str) {
		int totalLength = 0;
		char[] chars = str.toCharArray();
		for (char c : chars) {
			if (isChinese(c)) {
				totalLength += 2;
			} else {
				totalLength++;
			}
		}
		return totalLength;
	}

	/**
	 * 去除字符串中的HTML元素
	 * 
	 * @param str
	 *            待处理的字符串
	 * @return
	 */
	public static String removeHtmlTag(String str) {
		String htmlStr = str; // 含html标签的字符串
		String textStr = "";
		java.util.regex.Pattern p_script;
		java.util.regex.Matcher m_script;
		java.util.regex.Pattern p_html;
		java.util.regex.Matcher m_html;
		try {
			String regEx_html = "<[^>]+>"; // 定义HTML标签的正则表达式
			String regEx_script = "<[/s]*?script[^>]*?>[/s/S]*?<[/s]*?//[/s]*?script[/s]*?>"; // 定义script的正则表达式{或<script[^>]*?>[/s/S]*?<//script>

			p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
			m_script = p_script.matcher(htmlStr);
			htmlStr = m_script.replaceAll(""); // 过滤script标签

			p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
			m_html = p_html.matcher(htmlStr);
			htmlStr = m_html.replaceAll(""); // 过滤html标签

			textStr = htmlStr;
		} catch (Exception e) {
			System.err.println("Html2Text: " + e.getMessage());
		} finally {
			p_script = null;
			m_script = null;
			p_html = null;
			m_html = null;
		}
		return textStr;// 返回文本字符串
	}

	public static int lastIndexOf(String str1, String str2) {
		return str1.lastIndexOf(str2);
	}

	/**
	 * 获取起始年月中的所有年月，例如输入201201和201205将返回201201,201202,201203,201204,201205
	 * 
	 * @param minYearMonth
	 *            开始年月
	 * @param maxYearMonth
	 *            结束年月
	 * @return
	 * @throws ExceptionHandler
	 */
	public static List<String> yearMonthRange(String minYearMonth, String maxYearMonth) throws ExceptionHandler {
		List<String> yearMonthRange = new ArrayList<String>();
		yearMonthRange.add(minYearMonth);
		while (true) {
			String nextYearMonth = DateUtils.format(DateUtils.getMonth(DateUtils.parse(minYearMonth, DateUtils.yyyyMM), 1), DateUtils.yyyyMM);
			if (nextYearMonth.compareTo(maxYearMonth) <= 0) {
				minYearMonth = nextYearMonth;
				yearMonthRange.add(nextYearMonth);
			} else {
				break;
			}
		}
		return yearMonthRange;
	}

	/**
	 * 获取连续的年月，以当前月为基数，间隔intervals月数
	 * 
	 * @param intervals
	 * @return
	 * @throws ExceptionHandler
	 */
	public static List<String> yearMonthRange(int intervals) throws ExceptionHandler {
		Date base = DateUtils.getCurrDate();
		if (intervals > 0) {
			return yearMonthRange(DateUtils.format(base, DateUtils.yyyyMM), DateUtils.format(DateUtils.getMonth(base, intervals), DateUtils.yyyyMM));
		} else {
			return yearMonthRange(DateUtils.format(DateUtils.getMonth(base, intervals), DateUtils.yyyyMM), DateUtils.format(base, DateUtils.yyyyMM));
		}
	}

	/**
	 * 获取两个日期中间的所有日期
	 * 
	 * @param minDay
	 *            最小日期
	 * @param maxDay
	 *            最大日期
	 * @param pattern
	 *            日期格式
	 * @return
	 * @throws ExceptionHandler
	 */
	public static List<String> dayRange(Date minDay, Date maxDay, String pattern) throws ExceptionHandler {
		String minDayStr = DateUtils.format(minDay, pattern);
		String maxDayStr = DateUtils.format(maxDay, pattern);
		List<String> dayRange = new ArrayList<String>();
		dayRange.add(minDayStr);
		while (true) {
			Date nextDay = DateUtils.getDay(minDay, 1);
			minDayStr = DateUtils.format(nextDay, pattern);
			if (minDayStr.compareTo(maxDayStr) <= 0) {
				minDay = nextDay;
				dayRange.add(minDayStr);
			} else {
				break;
			}
		}
		return dayRange;
	}

	/**
	 * 获取汉字的查询码
	 * 
	 * @param chinese
	 *            汉字
	 * @return
	 */
	public static String qHelp(String chinese) {
		StringBuilder pinyin = new StringBuilder();
		StringBuilder wubi = new StringBuilder();
		int len = chinese.length();
		for (int i = 0; i < len; i++) {
			char c = chinese.charAt(i);

			if (isChinese(c)) {
				String[] temp = (String[]) Chinese.data.get(String.valueOf(c));
				if (temp != null) {
					pinyin.append(temp[0]);
					wubi.append(temp[1].charAt(0));
				}
			} else {
				pinyin.append(c);
				wubi.append(c);
			}
		}
		return pinyin.append(" ").append(wubi).append(" ").append(chinese).toString().toUpperCase();
	}

	/**
	 * 集合拼接
	 * 
	 * @param list
	 *            集合
	 * @param split
	 *            分隔符
	 * @return
	 */
	public static String join(List<String> list, String split) {
		if (list.size() > 0) {
			StringBuilder result = new StringBuilder();
			for (String s : list) {
				result.append(s).append(",");
			}
			return result.substring(0, result.length() - 1);
		} else {
			return null;
		}
	}

	/**
	 * 获取长日期字符串 将 yyyyMMddHHmmiss 转换为 yyyy-MM-dd HH:mm:ss 格式
	 * 
	 * @param shortDateStr
	 *            短日期字符窜
	 * @return
	 */
	public static String toLongDateStr(String shortDateStr) {
		if (shortDateStr == null || StringUtils.isEmpty(shortDateStr)) {
			return "";
		}
		if (shortDateStr.length() < 14) {
			return shortDateStr;
		}
		return shortDateStr.substring(0, 4) + "-" + shortDateStr.substring(4, 6) + "-" + shortDateStr.substring(6, 8) + " " + shortDateStr.substring(8, 10) + ":" + shortDateStr.substring(10, 12)
				+ ":" + shortDateStr.substring(12, 14);
	}

	/**
	 * 获取短日期字符串 将 yyyy-MM-dd HH:mm:ss 转换为 yyyyMMddHHmmiss 格式
	 * 
	 * @param longDateStr
	 *            短日期字符窜
	 * @return
	 */
	public static String toShortDateStr(String longDateStr) {
		return longDateStr.replaceAll("-", "").replaceAll(":", "").replaceAll(" ", "");
	}

	/**
	 * 多个对象字符串相加
	 * 
	 * @param objs
	 *            对象数组
	 * @return
	 */
	public static String toStrings(Object... objs) {
		StringBuilder str = new StringBuilder();
		for (Object obj : objs) {
			str.append(obj.toString());
		}
		return str.toString();
	}

	/**
	 * 两个对象字符串相加
	 * 
	 * @param obj1
	 *            对象1
	 * @param obj2
	 *            对象2
	 * @return
	 */
	public static String toString(Object obj1, Object obj2) {
		return toStrings(obj1, obj2);
	}

}
